`timescale 1ns/1ns
`define k 256
`define m 16

module ModOp(input clk,
			 input rst_n,
			 input curve_sel,
			 input mod,
			 //input [`k-1:0] p,
			 input [`k-1:0] mul_a,
			 input [`k-1:0] mul_b,
			 input 			mul_enable,
			 input [`k-1:0] add_a,
			 input [`k-1:0] add_b,
			 input 			func,
			 //input          modn,//模加做模n的加
			 input [`k-1:0] inv_a,//从T3中取
			 input 			inv_enable,
			 output [`k-1:0] mul_c,
			 output 	     mul_end_flag,
			 output [`k-1:0] add_c,
			 output [`k-1:0] inv_c,//存到T3
			 output 		 inv_end_flag
			);

wire [`k+`m+2:0] s_out,c_out;//寄存器S和C的输出,连接到模乘的输入和共享加法器的输入

//wire [`k:0] u_out,v_out;//连共享寄存器输出和共享加法器输入
wire [`k:0] u_out;

wire [`k-1:0] v_out;

reg [3:0] csa_sel,csa_p_sel,add_sel;//连接共享加法器的控制信号

wire [3:0] inv_csa_sel,inv_csa_p_sel,inv_add_sel;//连接模逆控制信号
wire [8:0] inv_r_sel;//连接模逆控制信号

reg [8:0] r_sel;//连接共享寄存器控制信号

wire [`k+`m+2:0] csa_in1,csa_in2;//连接共享寄存器输出和模逆输入

wire [`k+`m+2:0] csa_out;//连接共享寄存器输出和模逆输入
wire [`k:0] add_out;//连接共享寄存器输出和模逆输入

wire [`k+`m+2:0] mul_s_in,mul_c_in;//模乘的sum和carry输出，连接到共享寄存器的输入

wire mul_busy;

wire inv_busy;

wire [`k+`m+2:0] sc;//连模逆输出和共享寄存器输入

wire [`k:0] uv;//连模逆输出和共享寄存器输入

reg mul_1;

always @(*)
begin
	if(mul_enable)
		mul_1 = 1'b1;
	else if(mul_busy)
		mul_1 = 1'b1;
	else if(mul_end_flag)
		mul_1 = 1'b0;
	else
		mul_1 = 1'b0;
end

always @(*)
begin
	if(mul_1)
		r_sel = 9'b0101;
	else if((inv_busy) && (inv_end_flag == 1'b0))
		r_sel = inv_r_sel;
	else
		r_sel = 9'b00_00_111_11;
end

always @(*)
begin
	if(inv_busy)
		csa_sel = inv_csa_sel;
	else
		csa_sel = 4'b0101;
end

always @(*)
begin
	if(curve_sel == 1'b0)
		if(inv_busy)
			csa_p_sel = inv_csa_p_sel;
		else if(mod == 1'b0)
			if(func)
				csa_p_sel = 4'b1001;
			else
				csa_p_sel = 4'b0000;
		else if(mod)
			/*if(func)
				csa_p_sel = 4'b0110;
			else
				csa_p_sel = 4'b1000;
			*/
			csa_p_sel = 4'b1000;
		else
			csa_p_sel = 4'b0000;
	else
		if(inv_busy)
			csa_p_sel = inv_csa_p_sel;
		else if(mod == 1'b0)
			if(func)
				csa_p_sel = 4'b1011;
			else
				csa_p_sel = 4'b1010;
		else if(mod)
			if(func)
				csa_p_sel = 4'b0101;
			else
				csa_p_sel = 4'b1111;
		else
			csa_p_sel = 4'b1010;
end

always @(*)
begin
	if(inv_busy)
		add_sel = inv_add_sel;
	else
		add_sel = 4'b0101;
end

Mul_ecc MMM(.clk(clk),.rst_n(rst_n),.enable(mul_enable),.curve_sel(curve_sel),.a(mul_a),.b(mul_b),/*.p(p),*/.S(s_out),.C(c_out),.carry(mul_c_in),.sum(mul_s_in),.r(mul_c),.end_flag(mul_end_flag),.busy(mul_busy));

shared_adder shareadd(/*.p(p),*/.a_csa(add_a),.s_csa(s_out),.b_csa(add_b),.c_csa(c_out),.csa_sel(csa_sel),.func(func),.csa_p_sel(csa_p_sel),.a_add(add_a),.u_add(u_out),.b_add(add_b),.v_add(v_out),.add_sel(add_sel),.csa_in1(csa_in1),.csa_in2(csa_in2),.csa_out(csa_out),.add_out(add_out),.add_c(add_c));

RS_A modinv(.clk(clk),.rst_n(rst_n),.enable(inv_enable),.curve_sel(curve_sel),.mod(mod),/*.p(p),*/.csa_out(csa_out[274:1]),.add_out(add_out[256:1]),.c(c_out),.u(u_out[0]),.v(v_out),.csa_in1(csa_in1[0]),.csa_in2({csa_in2[`k+`m+2],csa_in2[0]}),.sc(sc),.uv(uv),.csa_sel(inv_csa_sel),.csa_p_sel(inv_csa_p_sel),.add_sel(inv_add_sel),.r_sel(inv_r_sel),.r(inv_c),.end_flag(inv_end_flag),.busy(inv_busy));

Register_ModOp REG_modop(.clk(clk),.rst_n(rst_n),/*.p(p),*/.curve_sel(curve_sel),.mod(mod),.s_in_m(mul_s_in),.s_in_a(sc),.c_in_m(mul_c_in),.c_in_a(sc),.u_in(uv),.v_in(uv[255:0]),.a(inv_a),.r_sel(r_sel),.s_out(s_out),.c_out(c_out),.u_out(u_out),.v_out(v_out));

endmodule